package kii.gui
{
	import flash.display.Loader;
	import flash.events.*;
	import flash.net.*;
	import flash.utils.*;
	import flash.system.LoaderContext;
	
	[Event(name = "complete", type="flash.events.Event")]
	[Event(name = "progress", type="flash.events.ProgressEvent")]
	[Event(name = "open", type="flash.events.Event")]
	[Event(name = "ioError", type="flash.events.IOErrorEvent")]
	
	public class StreamLoader extends Loader
	{
		protected var stream:URLStream = new URLStream();
		protected var bytes:ByteArray = new ByteArray();
		protected var loaderContext:LoaderContext;
		protected var timer:Timer;
		/**
		 * Constructor, creates new StreamLoader
		 * 
		 */
		public function StreamLoader(request:URLRequest = null)
		{
			if(request != null)
				loadStream(request);
		}
		/**
		 * Method, loads images as stream
		 * 
		 * @param	request		URLRequest
		 * @param	context		LoaderContext, default value is null
		 */
		public function loadStream(request:URLRequest, context:LoaderContext = null):void
		{
			loaderContext = context;
			
			stream.load(request);
			
			stream.addEventListener(Event.COMPLETE,onStreamComplete);
			stream.addEventListener(ProgressEvent.PROGRESS,onStreamProgress);
			stream.addEventListener(Event.OPEN,onStreamOpen);
			stream.addEventListener(IOErrorEvent.IO_ERROR,onStreamIOError);
			stream.addEventListener(HTTPStatusEvent.HTTP_STATUS,onStreamHTTPStatus);
			stream.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onStreamSecurityError);
		}
		/**
		 * @private
		 */
		private function onStreamComplete(event:Event):void
		{
			updateBytes();
			
			dispatchEvent(new Event(event.type, event.bubbles, event.cancelable));
			
			if(!timer)
				timer = new Timer(50, 1), timer.addEventListener(TimerEvent.TIMER_COMPLETE, confirmBytesLoaded);
			timer.start();		
		}
		/**
		 * @private
		 */
		private function onStreamProgress(event:ProgressEvent):void
		{
			updateBytes();
			dispatchEvent(new ProgressEvent(event.type, event.bubbles,
											event.cancelable, event.bytesLoaded, 
											event.bytesTotal));
			
		}
		/**
		 * @private
		 */
		private function onStreamIOError(event:IOErrorEvent):void
		{
			dispatchEvent(new IOErrorEvent(event.type, event.bubbles, event.cancelable, event.text));
		}
		/**
		 * @private
		 */
		private function onStreamSecurityError(event:SecurityErrorEvent):void
		{
			dispatchEvent(new SecurityErrorEvent(event.type, event.bubbles, event.cancelable, event.text));
		}
		/**
		 * @private
		 */
		private function onStreamHTTPStatus(event:HTTPStatusEvent):void
		{
			dispatchEvent(new HTTPStatusEvent(event.type, event.bubbles, event.cancelable, event.status));
		}
		/**
		 * @private
		 */
		private function onStreamOpen(event:Event):void
		{
			dispatchEvent(new Event(event.type, event.bubbles, event.cancelable));
		}
		/**
		 * @private
		 */
		private function updateBytes():void
		{
			stream.readBytes(bytes, bytes.length);
			
			if(bytes.length > 0)
				loadBytes(bytes, loaderContext);
		}
		/**
		 * @private
		 * 
		 * Method confirms that all bytes loaded, and closes stream
		 */
		private function confirmBytesLoaded(event:TimerEvent = null):void
		{
			updateBytes();
			stream.close();
			
			dispatchEvent(new Event(Event.COMPLETE));
			
			timer.reset();
			timer.stop();
		}
		
	}
}